package websocket

import (
	"fmt"
	"net/http"
	"strconv"
	"time"

	"github.com/gorilla/websocket"
	"github.com/zeromicro/go-zero/core/logx"
	"gorm.io/gorm"

	"data_service/models"
)

// NewWebSocketServer 创建新的WebSocket服务器
func NewWebSocketServer(db *gorm.DB) *WebSocketServer {
	sqlDB, _ := db.DB()
	sqlDB.SetMaxIdleConns(10)
	sqlDB.SetMaxOpenConns(100)
	sqlDB.SetConnMaxLifetime(time.Hour)

	server := &WebSocketServer{
		rooms:           make(map[string]*Room),
		gameRooms:       make(map[string]*GameRoom),
		roomListClients: make(map[string]*Client),
		upgrader: websocket.Upgrader{
			CheckOrigin: func(r *http.Request) bool {
				return true // 允许所有来源
			},
			ReadBufferSize:  1024,
			WriteBufferSize: 1024,
		},
		db: db,
	}

	// 初始化在线状态管理器
	server.onlineStatusManager = NewOnlineStatusManager(server)

	// 启动定时同步任务
	server.StartSyncTimer()

	return server
}

// GetRoom 获取房间
func (s *WebSocketServer) GetRoom(id string) *Room {
	s.roomsMu.RLock()
	defer s.roomsMu.RUnlock()
	return s.rooms[id]
}

// GetGameRoom 获取游戏房间
func (s *WebSocketServer) GetGameRoom(id string) *GameRoom {
	s.gameRoomsMu.RLock()
	defer s.gameRoomsMu.RUnlock()
	return s.gameRooms[id]
}

// CreateRoom 创建房间（统一使用数据库ID）
func (s *WebSocketServer) CreateRoom(name, roomType, creatorID, creatorName string, maxUsers int) *Room {
	// 先创建数据库记录
	var dbRoom *models.Room
	if s.db != nil {
		dbRoom = &models.Room{
			Name: name,
			CreatorID: func() int {
				if id, err := strconv.Atoi(creatorID); err == nil {
					return id
				} else {
					return 0
				}
			}(),
			CreatorName: creatorName,
			Tag:         roomType,
			MaxUsers:    maxUsers,
		}
		if err := s.db.Create(dbRoom).Error; err != nil {
			logx.Errorf("[CreateRoom] 创建数据库房间失败: %v", err)
			return nil
		}
	}

	// 使用数据库ID创建WebSocket房间
	roomID := fmt.Sprintf("%d", dbRoom.ID)
	room := &Room{
		ID:          roomID,
		Name:        name,
		Type:        roomType,
		CreatorID:   creatorID,
		CreatorName: creatorName,
		Clients:     make(map[string]*Client),
		UserNames:   make(map[string]string),
		JoinTimes:   make(map[string]int64),
		Ready:       make(map[string]bool),
		MaxUsers:    maxUsers,
		Messages:    make([]*Message, 0),
		server:      s,
	}

	if roomType == "chat" {
		s.roomsMu.Lock()
		s.rooms[roomID] = room
		s.roomsMu.Unlock()
	} else {
		// 游戏房间
		gameRoom := &GameRoom{Room: room}
		s.gameRoomsMu.Lock()
		s.gameRooms[roomID] = gameRoom
		s.gameRoomsMu.Unlock()
	}

	logx.Infof("[CreateRoom] 创建房间成功: ID=%s, 名称=%s, 类型=%s", roomID, name, roomType)
	return room
}

// CreateRoomFromDB 从数据库房间创建WebSocket房间
func (s *WebSocketServer) CreateRoomFromDB(dbRoom *models.Room) *Room {
	roomIDStr := fmt.Sprintf("%d", dbRoom.ID)
	roomType := dbRoom.Tag
	if roomType == "" {
		roomType = "chat"
	}

	room := &Room{
		ID:          roomIDStr,
		Name:        dbRoom.Name,
		Type:        roomType,
		CreatorID:   fmt.Sprintf("%d", dbRoom.CreatorID),
		CreatorName: dbRoom.CreatorName,
		Clients:     make(map[string]*Client),
		UserNames:   make(map[string]string),
		JoinTimes:   make(map[string]int64),
		Ready:       make(map[string]bool),
		MaxUsers:    dbRoom.MaxUsers,
		Messages:    make([]*Message, 0),
		server:      s,
	}

	if roomType == "chat" {
		s.roomsMu.Lock()
		s.rooms[roomIDStr] = room
		s.roomsMu.Unlock()
	} else {
		// 游戏房间
		gameRoom := &GameRoom{Room: room}
		s.gameRoomsMu.Lock()
		s.gameRooms[roomIDStr] = gameRoom
		s.gameRoomsMu.Unlock()
	}

	logx.Infof("[CreateRoomFromDB] 从数据库创建WebSocket房间: %s (类型: %s)", roomIDStr, roomType)
	return room
}

// AddClient 添加客户端到房间
func (r *Room) AddClient(client *Client) {
	r.mu.Lock()
	defer r.mu.Unlock()

	// 检查房间是否已满
	if len(r.Clients) >= r.MaxUsers {
		logx.Errorf("[Room.AddClient] 房间 %s 已满，拒绝用户 %s 加入", r.ID, client.UserName)
		return
	}

	// 取消房间自动销毁定时器
	if r.destroyTimer != nil {
		r.destroyTimer.Stop()
		r.destroyTimer = nil
	}

	// 添加到WebSocket房间
	r.Clients[client.UserID] = client
	r.UserNames[client.UserID] = client.UserName
	r.JoinTimes[client.UserID] = time.Now().Unix()
	r.Ready[client.UserID] = false

	// 广播用户加入消息
	joinMsg := Message{
		Type:     int(MessageTypeJoin),
		UserID:   client.UserID,
		UserName: client.UserName,
		Content:  fmt.Sprintf("%s 加入了房间", client.UserName),
		Time:     time.Now().Unix(),
	}
	r.Broadcast(joinMsg)

	// 广播用户列表更新
	r.BroadcastUserListUpdate()

	// 广播房间人数更新
	r.BroadcastRoomUserCount()

	// 广播房间列表更新
	if r.server != nil {
		go r.server.BroadcastRoomListUpdate()
	}

	logx.Infof("[Room.AddClient] 用户 %s 加入房间 %s", client.UserName, r.ID)
}

// RemoveClient 从房间移除客户端
func (r *Room) RemoveClient(client *Client) {
	r.mu.Lock()
	defer r.mu.Unlock()

	// 检查客户端是否还在房间中
	if _, exists := r.Clients[client.UserID]; !exists {
		return
	}

	delete(r.Clients, client.UserID)
	delete(r.UserNames, client.UserID)
	delete(r.JoinTimes, client.UserID)
	delete(r.Ready, client.UserID)

	userName := client.UserName

	// 安全关闭客户端连接
	client.Close()

	// 广播用户离开消息
	leaveMsg := Message{
		Type:     int(MessageTypeLeave),
		UserID:   client.UserID,
		UserName: userName,
		Content:  fmt.Sprintf("%s 离开了房间", userName),
		Time:     time.Now().Unix(),
	}
	r.Broadcast(leaveMsg)

	// 广播用户列表更新
	r.BroadcastUserListUpdate()

	// 广播房间人数更新
	r.BroadcastRoomUserCount()

	// 广播房间列表更新
	if r.server != nil {
		go r.server.BroadcastRoomListUpdate()
	}

	// 检查房间是否为空
	if len(r.Clients) == 0 {
		r.scheduleDestroy()
	}

	logx.Infof("[Room.RemoveClient] 用户 %s 离开房间 %s", userName, r.ID)
}

// Broadcast 广播消息到房间
func (r *Room) Broadcast(msg Message) {
	r.mu.RLock()
	clients := make([]*Client, 0, len(r.Clients))
	for _, client := range r.Clients {
		// 只向已连接的客户端发送消息
		if client.IsConnected() {
			clients = append(clients, client)
		}
	}
	r.mu.RUnlock()

	for _, client := range clients {
		select {
		case client.Send <- msg.ToJSON():
		default:
			// 通道已满，跳过
			logx.Errorf("[Room.Broadcast] 客户端 %s 发送通道已满", client.UserName)
		}
	}
}

// GetUserList 获取用户列表
func (r *Room) GetUserList() []map[string]interface{} {
	r.mu.RLock()
	defer r.mu.RUnlock()

	users := make([]map[string]interface{}, 0, len(r.Clients))
	for userID, userName := range r.UserNames {
		users = append(users, map[string]interface{}{
			"user_id":   userID,
			"user_name": userName,
			"ready":     r.Ready[userID],
		})
	}
	return users
}

// scheduleDestroy 安排房间自动销毁
func (r *Room) scheduleDestroy() {
	if r.destroyTimer != nil {
		r.destroyTimer.Stop()
	}

	r.destroyTimer = time.AfterFunc(30*time.Second, func() {
		r.mu.Lock()
		if len(r.Clients) > 0 {
			r.mu.Unlock()
			return
		}
		r.mu.Unlock()

		// 销毁房间
		if r.Type == "chat" {
			r.server.roomsMu.Lock()
			delete(r.server.rooms, r.ID)
			r.server.roomsMu.Unlock()
		} else {
			r.server.gameRoomsMu.Lock()
			delete(r.server.gameRooms, r.ID)
			r.server.gameRoomsMu.Unlock()
		}

		logx.Infof("[Room.scheduleDestroy] 房间 %s 已销毁", r.ID)
	})
}

// BroadcastRoomListUpdate 广播房间列表更新
func (s *WebSocketServer) BroadcastRoomListUpdate() {
	roomsInfo := s.GetAllRoomsInfo()
	msg := Message{
		Type: int(MessageTypeRoomListUpdate),
		Data: map[string]interface{}{"rooms": roomsInfo},
		Time: time.Now().Unix(),
	}

	s.roomListMu.RLock()
	clients := make([]*Client, 0, len(s.roomListClients))
	for _, client := range s.roomListClients {
		clients = append(clients, client)
	}
	s.roomListMu.RUnlock()

	for _, client := range clients {
		select {
		case client.Send <- msg.ToJSON():
		default:
			// 通道已满，跳过
		}
	}
}

// BroadcastUserListUpdate 广播用户列表更新
func (r *Room) BroadcastUserListUpdate() {
	users := r.GetUserList()
	msg := Message{
		Type:    int(MessageTypeUserListUpdate),
		Content: "",
		Data:    map[string]interface{}{"users": users},
		Time:    time.Now().Unix(),
	}
	r.Broadcast(msg)
}

// BroadcastRoomUserCount 广播房间人数更新
func (r *Room) BroadcastRoomUserCount() {
	r.mu.RLock()
	userCount := len(r.Clients)
	r.mu.RUnlock()

	msg := Message{
		Type:    int(MessageTypeRoomUserCount),
		Content: "",
		Data:    map[string]interface{}{"user_count": userCount, "max_users": r.MaxUsers},
		Time:    time.Now().Unix(),
	}
	r.Broadcast(msg)
}

// GetAllRoomsInfo 获取所有房间信息（WebSocket实时数据）
func (s *WebSocketServer) GetAllRoomsInfo() []map[string]interface{} {
	var roomsInfo []map[string]interface{}

	// 从数据库获取房间基本信息
	if s.db != nil {
		var dbRooms []models.Room
		s.db.Order("id DESC").Find(&dbRooms)
		logx.Infof("[GetAllRoomsInfo] 从数据库获取到 %d 个房间", len(dbRooms))

		// 获取WebSocket实时数据
		s.roomsMu.RLock()
		wsRooms := make(map[string]*Room)
		for id, room := range s.rooms {
			wsRooms[id] = room
		}
		s.roomsMu.RUnlock()

		s.gameRoomsMu.RLock()
		wsGameRooms := make(map[string]*GameRoom)
		for id, gameRoom := range s.gameRooms {
			wsGameRooms[id] = gameRoom
		}
		s.gameRoomsMu.RUnlock()

		logx.Infof("[GetAllRoomsInfo] WebSocket中有 %d 个普通房间, %d 个游戏房间", len(wsRooms), len(wsGameRooms))

		// 合并数据库房间信息和WebSocket实时用户数
		for _, dbRoom := range dbRooms {
			roomInfo := map[string]interface{}{
				"id":           dbRoom.ID,
				"name":         dbRoom.Name,
				"creator_id":   dbRoom.CreatorID,
				"creator_name": dbRoom.CreatorName,
				"tag":          dbRoom.Tag,
				"max_users":    dbRoom.MaxUsers,
				"is_playing":   dbRoom.IsPlaying,
				"created_at":   dbRoom.CreatedAt,
				"updated_at":   dbRoom.UpdatedAt,
			}

			// 查找对应的WebSocket房间，获取实时用户数
			dbRoomIDStr := fmt.Sprintf("%d", dbRoom.ID)
			var userCount int

			if room, exists := wsRooms[dbRoomIDStr]; exists {
				room.mu.RLock()
				userCount = len(room.Clients)
				room.mu.RUnlock()
				logx.Infof("[GetAllRoomsInfo] 房间 %d: WebSocket实时用户数=%d", dbRoom.ID, userCount)
			} else if gameRoom, exists := wsGameRooms[dbRoomIDStr]; exists {
				gameRoom.Room.mu.RLock()
				userCount = len(gameRoom.Room.Clients)
				gameRoom.Room.mu.RUnlock()
				logx.Infof("[GetAllRoomsInfo] 房间 %d: WebSocket实时用户数=%d", dbRoom.ID, userCount)
			} else {
				userCount = 0
				logx.Infof("[GetAllRoomsInfo] 房间 %d: 无WebSocket连接，用户数=0", dbRoom.ID)
			}

			roomInfo["user_count"] = userCount
			roomsInfo = append(roomsInfo, roomInfo)
		}
	}

	logx.Infof("[GetAllRoomsInfo] 返回房间信息: %d 个房间", len(roomsInfo))
	return roomsInfo
}

// GetRooms 获取所有普通房间
func (s *WebSocketServer) GetRooms() map[string]*Room {
	s.roomsMu.RLock()
	defer s.roomsMu.RUnlock()

	rooms := make(map[string]*Room)
	for id, room := range s.rooms {
		rooms[id] = room
	}
	return rooms
}

// GetGameRooms 获取所有游戏房间
func (s *WebSocketServer) GetGameRooms() map[string]*GameRoom {
	s.gameRoomsMu.RLock()
	defer s.gameRoomsMu.RUnlock()

	gameRooms := make(map[string]*GameRoom)
	for id, room := range s.gameRooms {
		gameRooms[id] = room
	}
	return gameRooms
}

// DeleteRoom 删除房间
func (s *WebSocketServer) DeleteRoom(id string) {
	s.roomsMu.Lock()
	delete(s.rooms, id)
	s.roomsMu.Unlock()
}

// DeleteGameRoom 删除游戏房间
func (s *WebSocketServer) DeleteGameRoom(id string) {
	s.gameRoomsMu.Lock()
	delete(s.gameRooms, id)
	s.gameRoomsMu.Unlock()
}

// StartSyncTimer 启动同步定时器（简化版本）
func (s *WebSocketServer) StartSyncTimer() {
	// 移除复杂的同步逻辑，只保留基本的房间管理
	logx.Infof("[StartSyncTimer] 房间同步已简化，仅使用WebSocket实时数据")
}
